package com.ts.main.mini.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ts.main.mini.constants.JwtConstant;
import com.ts.main.mini.constants.RedisPrefixConstants;
import com.ts.main.mini.utils.JwtTokenUtil;
import com.ts.main.mini.utils.RedisUtil;
import com.ts.main.mini.context.UserContext;
import com.ts.main.mini.dto.UserDto;
import com.ts.main.mini.entity.UserEntity;
import com.ts.main.mini.exception.CommonException;
import com.ts.main.mini.mapper.UserMapper;
import com.ts.main.mini.po.UserPo;
import com.ts.main.mini.properties.WxPayProperties;
import com.ts.main.mini.vo.UserPolicyVo;
import com.ts.main.mini.vo.UserVo;
import io.micrometer.common.util.StringUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lk
 * @description 针对表【t_user(用户表)】的数据库操作Service实现
 * @createDate 2025-05-16 15:12:04
 */
@Slf4j
@AllArgsConstructor
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> {

    private final WxPayProperties wxPayProperties;

    private final RedisUtil redisUtil;

    private final RestTemplate restTemplate;

    public UserPo getUserInfo(String phone) {
        return baseMapper.getUserInfo(phone);
    }

    /**
     * 微信凭证
     *
     * @return
     */
    public String getAccessToken() {
        // 使用稳定版AccessToken接口
        String url = "https://api.weixin.qq.com/cgi-bin/stable_token";
        // 构建请求参数
        Map<String, String> params = new HashMap<>();
        params.put("grant_type", "client_credential");
        params.put("appid", wxPayProperties.getAppid());
        params.put("secret", wxPayProperties.getSecret());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, String>> request = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
        if (!response.getStatusCode().is2xxSuccessful()) {
            throw new CommonException("微信接口请求失败，状态码: " + response.getStatusCodeValue());
        }
        String responseBody = response.getBody();
        JSONObject json = JSON.parseObject(responseBody);
        // 检查微信接口返回错误
        if (json.containsKey("errcode")) {
            int errcode = json.getIntValue("errcode");
            if (errcode != 0) {
                String errmsg = json.getString("errmsg");
                log.error("微信接口返回错误: errcode={}, errmsg={}", errcode, errmsg);
                throw new CommonException("获取AccessToken失败: " + errmsg + " (错误码: " + errcode + ")");
            }
        }
        // 解析返回结果
        if (json.containsKey("access_token")) {
            return json.getString("access_token");
        } else {
            throw new CommonException("获取AccessToken失败，响应中未包含access_token");
        }
    }

    public String getUserPhone(String code) {
        // 验证输入参数有效性
        if (ObjectUtil.isEmpty(code)) {
            throw new IllegalArgumentException("code不能为空");
//            return null;
        }
        String accessToken = getAccessToken();
        //String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
        String url = String.format("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s", accessToken);
        // 构建JSON请求体
        JSONObject requestJson = new JSONObject();
        requestJson.put("code", code);
        // 设置HTTP头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> entity = new HttpEntity<>(requestJson.toString(), headers);
        try {
            // 发送POST请求
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, entity, String.class);
            String responseBody = responseEntity.getBody();
            // 解析响应并处理错误
            JSONObject json = JSON.parseObject(responseBody);
            Integer errcode = json.getInteger("errcode");
            if (errcode != null && errcode != 0) {
                String errmsg = json.getString("errmsg");
                throw new CommonException("获取手机号失败, 错误码: " + errcode + ", 错误信息: " + errmsg);
            }
            // 提取手机号
            JSONObject phoneInfo = json.getJSONObject("phone_info");
            if (phoneInfo != null) {
                return phoneInfo.getString("phoneNumber");
            } else {
                throw new CommonException("微信返回数据格式异常: 未能找到手机号信息");
            }
        } catch (RestClientException e) {
            throw new CommonException("获取手机号失败，code无效或请求失败：" + e.getMessage());
        }
    }

    public String getUserOpenid(String code) {
        // 验证输入参数有效性
        if (ObjectUtil.isEmpty(code)) {
            throw new IllegalArgumentException("code不能为空");
        }
        // 1. 调用微信API获取openid
        // 构造请求URL
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                wxPayProperties.getAppid(), wxPayProperties.getSecret(), code);
        // 调用微信API获取响应
        String response = restTemplate.getForObject(url, String.class);
        // 解析返回的JSON
        JSONObject json = JSON.parseObject(response);
        // 2. 验证响应中的错误信息
        if (json.containsKey("errcode")) {
            int errcode = json.getIntValue("errcode");
            String errmsg = json.getString("errmsg");
            throw new CommonException("微信API错误: " + errcode + " - " + errmsg);
        }
        // 3. 获取openid并验证其有效性
        String openid = json.getString("openid");
        if (ObjectUtil.isEmpty(openid)) {
            throw new CommonException("openid获取失败");
        }
        log.info("openid：{}" + openid);
        return openid;
    }


    /**
     * 用户登录（手机号）
     *
     * @param phone
     * @return
     */
    public UserVo login(String phone, String openid) {
        UserPo userInfo = getUserInfo(phone);
        //注册
        if (ObjectUtil.isEmpty(userInfo)) {
            UserEntity user = new UserEntity();
            user.setRoleId(2)
                    .setPhone(phone)
                    .setPassword(phone)
                    .setOpenid(openid)
                    .setUserName("沱舍定制SVIP");
            save(user);
            userInfo = getUserInfo(phone);
        } else {
            //更新openid
            if (!StringUtils.isEmpty(openid)) {
                //检验
                LambdaUpdateWrapper<UserEntity> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper
                        .set(UserEntity::getOpenid, openid)
                        .eq(UserEntity::getPhone, phone);
                update(updateWrapper);
            }
        }
        //用户信息
        UserVo userVo = new UserVo();
        BeanUtil.copyProperties(userInfo, userVo);
        // 生成 JWT Token
        long expireTime = JwtConstant.EXPIRATION_REMEMBER;
        String token = JwtTokenUtil.createToken(userVo.getPhone(), expireTime);
        userVo.setToken(token);
        // 更新用户信息缓存
        redisUtil.setObject(RedisPrefixConstants.USER_INFO + userVo.getPhone(), userVo, expireTime);
        // 设置当前用户上下文
        UserContext.setUser(userVo);
        return userVo;
    }


    @Transactional
    public Boolean updateUserInfo(UserDto dto) {
        UserVo user = UserContext.getUser();
        dto.setUserId(user.getUserId());
        // 更新用户信息
        LambdaUpdateWrapper<UserEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(UserEntity::getUserName, dto.getUserName())
                .set(UserEntity::getGender, dto.getGender())
                .set(UserEntity::getEmail, dto.getEmail())
                .set(UserEntity::getHeadImage, dto.getHeadImage())
                .eq(UserEntity::getUserId, dto.getUserId());
        update(updateWrapper);
        // 获取用户信息并更新缓存
        UserPo userPo = getUserInfo(user.getPhone());
        BeanUtil.copyProperties(userPo, user);
        // 更新缓存，覆盖现有缓存
        redisUtil.setObject(RedisPrefixConstants.USER_INFO + user.getPhone(), user, JwtConstant.EXPIRATION_REMEMBER);
        // 更新当前用户上下文信息
        UserContext.setUser(user);
        return Boolean.TRUE;
    }


    public Boolean logout() {
        UserVo user = UserContext.getUser();
        // 更新用户信息缓存
        redisUtil.deleteKey(RedisPrefixConstants.USER_INFO + user.getPhone());
        UserContext.clearUser();
        return true;
    }

    public Boolean logoff() {
        UserVo user = UserContext.getUser();
        LambdaUpdateWrapper<UserEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(UserEntity::getIsDeleted, true)
                .eq(UserEntity::getUserId, user.getUserId());
        update(updateWrapper);
        // 更新用户信息缓存
        redisUtil.deleteKey(RedisPrefixConstants.USER_INFO + user.getPhone());
        UserContext.clearUser();
        return true;
    }

    public UserPolicyVo getUserPolicy() {
        UserPolicyVo userPolicyVo = new UserPolicyVo();
        userPolicyVo.setUserAgreement("2025-06-11/1932676496271478784.pdf");
        userPolicyVo.setPrivacyPolicy("2025-06-11/1932676597350010880.pdf");
        return userPolicyVo;
    }
}




